/**
 * 
 */
package org.youisoft.summer.evaluator.function.base;

import org.youisoft.summer.evaluator.InvokeException;
import org.youisoft.summer.evaluator.context.CalContext;
import org.youisoft.summer.evaluator.function.AbstractFunction;
import org.youisoft.summer.evaluator.operator.Operator;
import org.youisoft.summer.evaluator.operator.base.NullOperator;
import org.youisoft.summer.evaluator.operator.base.NumberOperator;
import org.youisoft.summer.evaluator.operator.base.StringOperator;

/**
 * @author zijiang.jl
 *
 */
public abstract class AbstractArithmeticFunction  extends AbstractFunction{
	private static final java.util.List<Class<?>> supports;
	static{
		supports=new java.util.ArrayList<Class<?>>();
		supports.add(NumberOperator.class);
		supports.add(StringOperator.class);
		supports.add(NullOperator.class);
	}
	

	@Override
	protected boolean checkOperator(int index, Operator<?> operator) {
		return supports.contains(operator.getClass());
	}


	
	@Override
	public <C,R,P> Operator<?> doInvoke(CalContext<C,R,P> context,Operator<?>... operator) throws InvokeException{
		if(operator[0] instanceof NullOperator) return operator[1];
		if(operator[1] instanceof NullOperator) return operator[0];
		
		if(operator[0] instanceof StringOperator||operator[1] instanceof StringOperator){
			StringOperator o1=null;
			StringOperator o2=null;
			if(operator[0] instanceof NumberOperator){
				o1=new StringOperator(operator[0].value().toString());
			}else{
				o1=(StringOperator)operator[0];
			}
			
			if(operator[1] instanceof NumberOperator){
				o2=new StringOperator(operator[1].value().toString());
			}else{
				o2=(StringOperator)operator[1];
			}
			return this.doInvoke(context, o1,o2);
		}
		
		
		if(operator[0] instanceof NumberOperator&&operator[1] instanceof NumberOperator){
			NumberOperator o1=(NumberOperator)operator[0];
			NumberOperator o2=(NumberOperator)operator[1];
			return this.doInvoke(context, o1,o2);
		}
		
		return Operator.nullInstance;
	}
	
	protected abstract <C,R,P> Operator<?> doInvoke(CalContext<C,R,P> context,StringOperator... operator) throws InvokeException;
	

	protected abstract <C,R,P> Operator<?> doInvoke(CalContext<C,R,P> context,NumberOperator... operator) throws InvokeException;
	
	
	@Override
	protected int minOperatorCount() {
		return 2;
	}
}
